<template>
  <div>
    <el-container>
      <el-aside width="400px">
        <div>
          <el-button @click="openCamera" style="margin-top: 20px">打开摄像头</el-button>
          <el-button type="success" @click="takePhoto" style="margin-top: 20px">拍照识别</el-button>
          <video ref="video" width="320" height="240"></video>
          <canvas ref="canvas" width="320" height="240" style="display: none;"></canvas>
          <!--    <img :src="photoDataUrl" alt="拍照的图片">-->
        </div>
        <el-row>
          <el-col :span="12">
            <el-upload style="margin-left: 40px;margin-top: 40px"
                       ref="uploadRef"
                       class="avatar-uploader"
                       :show-file-list="false"
                       :auto-upload="true"
                       action="http://localhost:8088/file/upload2"
                       name="file"
                       :on-success="res => uploadSuccess(res.data)"
            >
              <img v-if="imgUrl" :src="imgUrl" class="avatar" width="333"/>
              <img v-else src="@/assets/avatar2.png" width="333"/>
            </el-upload>
          </el-col>
        </el-row>
        <el-divider></el-divider>
      </el-aside>
      <el-container>
        <el-header class="styled-header">
          <el-menu mode="horizontal" router="router">
            <el-menu-item index="/drug">药品检索</el-menu-item>
            <el-menu-item index="/case">病例说明</el-menu-item>
            <el-menu-item index="/symptom">症状查询</el-menu-item>
            <el-menu-item index="/place">医院信息查找</el-menu-item>
            <el-button type="text" >？使用说明</el-button>
          </el-menu>
        </el-header>
        <el-main
            style=" align-items: center; flex-direction: column; height: 580px; max-width: 100%;">
          <el-card shadow="hover" style="margin-right: 5px;width: 720px">
            <el-descriptions class="margin-top" :column="3">
              <el-descriptions-item label="病例概要分析">
                <div v-html="messages"></div>
              </el-descriptions-item>
            </el-descriptions>
            <el-button type="success" @click="speakTtsSpeech">语音播报</el-button>
          </el-card>
        </el-main>
      </el-container>
    </el-container>
    <el-dialog
        title="提示"
        :visible.sync="centerDialogVisible"
        width="70%"
        center>
      <div style="display: flex;">
        <span><img src="@/assets/helpme1.png" style="width: 80%; height: auto;" alt=""/></span>
        <span><img src="@/assets/helpme2.png" style="width: 80%; height: 80%;" alt=""/></span>
      </div>
      <span slot="footer" class="dialog-footer">
      <el-button type="primary" @click="centerDialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import request from "@/utils/request";
import Speech from 'speak-tts'

export default {

  data() {
    return {
      //图片上传功能
      imgUrl: '',
      dialogImageUrl: '',
      dialogVisible: false,
      doName: '',
      //主显示内容
      messages: '',
      speech: '',
      //使用说明
      centerDialogVisible: false,
      //拍的照片存储的容器
      photoDataUrl: '',
      stream: null,
      videoElement: null,
      canvasElement: null,
    };
  },
  methods: {
    // 播报系统js
    //初始化播报系统
    speechInit() {
      this.speech = new Speech();
      this.speech.setLanguage("zh-CN");
      this.speech.init().then(() => {
      });
    },
    //为按钮添加了点击播报事件
    speakTtsSpeech() {
      this.speech.speak({text: this.messages}).then(() => {
      });
    },
    //图片上传成功的回调 先是显示图片 再进行chat问答
    uploadSuccess(data) {
      this.imgUrl = data.url
      this.askChat(data.name)
    },
    handleRemove(file, fileList) {
      console.log(file, fileList);
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    //摄像头上传拍照
    openCamera() {
      /*
      调用了 navigator.mediaDevices.getUserMedia 方法
      该方法请求用户授权访问本地设备（例如摄像头、麦克风等） 并返回一个 Promise 对象。
      调用该方法时，代码传入一个配置对象，指定要访问的设备类型
      例如 { video: true } 表示要获取视频流。调用 then 方法来处理成功的情况
      */
      navigator.mediaDevices.getUserMedia({video: true})
          .then((stream) => {
            //将视频流赋值给 Vue 实例的 stream 属性
            this.stream = stream;
            //视频流绑定到 HTML5 的 video 元素上，使用 srcObject 属性来实现，并调用 play 方法播放视频
            this.videoElement.srcObject = stream;
            this.videoElement.play();
            //通过以上的这样的操作，即可实现摄像头视频流的捕获和展示。
          })
          .catch((error) => {
            console.error('打开摄像头失败：', error);
          });
    },
    takePhoto() {
      // 获取 Canvas 元素的上下文对象
      const context = this.canvasElement.getContext('2d');

      // 将视频元素中当前帧的图像绘制到 Canvas 中
      context.drawImage(this.videoElement, 0, 0, this.canvasElement.width, this.canvasElement.height);

      // 将 Canvas 中的图像转换为 Blob 对象
      this.canvasElement.toBlob((blob) => {
        // 创建一个 File 对象
        const file = new File([blob], 'photo.jpg', {type: 'image/jpeg'});

        // 调用 getTracks() 方法遍历摄像头视频流的所有轨道，并逐一停止它们，这样就关闭了摄像头
        this.stream.getTracks().forEach((track) => {
          track.stop();
        });
        // 发送文件给后台
        this.askChatByPhoto(file);
      }, 'image/jpeg');
    },

    async askChat(value) {
      var _this = this
      _this.messages=""
      const response = await fetch('http://localhost:8088/ai/caseAiSearch', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({name: value})
      });
      if (response.ok) {
        const reader = response.body.getReader();
        const stream = new ReadableStream({
          async start(controller) {
            function fetchData() {
              reader.read().then(({done, value}) => {
                if (done) {
                  controller.close();
                  return;
                }
                const chunkText = new TextDecoder().decode(value);
                async function processChunkText(chunkText) {
                  try {
                    const dataArray = JSON.parse(chunkText);
                    for (const data of dataArray) {
                      if (data.end === true) {
                        return;
                      }
                      if (data.result) {
                        const text = data.result;
                        // 假设 _this 是当前上下文的引用，确保它在函数外部已经定义
                        _this.messages += text;
                        // 休眠一秒钟
                        await new Promise(resolve => setTimeout(resolve, 1000));
                      }
                    }
                  } catch (error) {
                    // 处理 JSON.parse 可能出现的错误
                    console.error('Error parsing JSON:', error);
                  }
                }
                processChunkText(chunkText)
                fetchData();
              });
            }
            fetchData();
          }
        });
        console.log(_this.messages)
        await new Response(stream).text();
      } else {
        this.$message.error('发生错误')
      }
    },

    async askChatByPhoto(file) {
      const formData = new FormData();
      formData.append('file', file);
      var _this = this
      _this.messages=""
      const response = await fetch('http://localhost:8088/ai/caseAiSearchByphoto', {
        method: 'POST',
        body: formData
      });
      if (response.ok) {
        const reader = response.body.getReader();
        const stream = new ReadableStream({
          async start(controller) {
            function fetchData() {
              reader.read().then(({done, value}) => {
                if (done) {
                  controller.close();
                  return;
                }
                const chunkText = new TextDecoder().decode(value);
                async function processChunkText(chunkText) {
                  try {
                    const dataArray = JSON.parse(chunkText);
                    for (const data of dataArray) {
                      if (data.end === true) {
                        return;
                      }
                      if (data.result) {
                        const text = data.result;
                        // 假设 _this 是当前上下文的引用，确保它在函数外部已经定义
                        _this.messages += text;
                        // 休眠一秒钟
                        await new Promise(resolve => setTimeout(resolve, 1000));
                      }
                    }
                  } catch (error) {
                    // 处理 JSON.parse 可能出现的错误
                    console.error('Error parsing JSON:', error);
                  }
                }
                processChunkText(chunkText)
                fetchData();
              });
            }
            fetchData();
          }
        });
        console.log(_this.messages)
        await new Response(stream).text();
      } else {
        this.$message.error('发生错误')
      }
    }
  },
  mounted() {
    this.speechInit();
    //通过 ref 获取到的 video 元素赋值给组件实例的 videoElement 属性
    this.videoElement = this.$refs.video;
    //通过 ref 获取到的 canvas 元素赋值给组件实例的 canvasElement 属性
    this.canvasElement = this.$refs.canvas;
  }
}
</script>

<style>
.styled-header {
  font-size: 24px; /* 设置字体大小 */
  font-weight: bold; /* 设置字体加粗 */
  color: #333; /* 设置字体颜色 */
  text-align: center; /* 设置文本居中 */
  padding: 20px 0; /* 设置上下内边距 */
  border-bottom: 2px solid #ccc; /* 添加底部边框 */
  background-color: #f0f0f0; /* 设置背景颜色 */
}

.el-header {

  background-color: #cedaf8;
  text-align: center;
}

.el-aside {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
}

.el-main {
  background-color: #f0f0f0;
  color: #333;
  text-align: center;

}

.text {
  font-size: 14px;
}

.item {
  padding: 18px 0;
}


.box-card1 {
  width: 968px;
  margin-top: 10px;
}
</style>